package com.csipsimple.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.csipsimple.db.DBAdapter;
import com.csipsimple.models.CallerInfo;
import com.csipsimple.ui.WebLogOn;
import com.csipsimple.utils.Log;
import com.urnum.R;


import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.PhoneLookup;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.provider.ContactsContract.CommonDataKinds.Phone;

public class OutgoingPSTN  extends Activity{
	String callNumber;
	String callName;
	String cachedCallName;
	String cachedCallType;
	long callStart;
	String bNumber;
	String aNumber;
	String cc;
	Boolean isCancelled;
	final String code= "*U+Rn*%u-+m";
	static final int WEB_LOGON_REQUEST = 7; 
	protected DBAdapter db;
	PhoneStateListener mListener;
	TelephonyManager mTelMgr; 
	AlertDialog.Builder alert; 
	   private String executeHttpGet(String urnum) throws Exception {
	        BufferedReader in = null;
	        try {
	            HttpClient client = new DefaultHttpClient();
	            HttpGet request = new HttpGet();
	            request.setURI(new URI("http://www.urnum.com/app?u="+urnum+"&a="+aNumber+"&cc="+cc));
	            HttpResponse response = client.execute(request);
	            in = new BufferedReader
	            (new InputStreamReader(response.getEntity().getContent()));
	            StringBuffer sb = new StringBuffer("");
	            String line = "";
	            while ((line = in.readLine()) != null) {
	                sb.append(line);
	            }
	            in.close();
	            String page = sb.toString();
	            return page;
	        } finally {
	            if (in != null) {
	                try {
	                    in.close();
	                    } catch (IOException e) {
	                    e.printStackTrace();
	                }
	            }
	        }
	   }

	private String numberFromUrnum(String number) {
		String returnNumber = null;
	
		if (number.length()>=12  && number.substring(0,11).equals(code)){
			returnNumber = number.substring(11);
		}
		else{
		returnNumber = db.getShortcode(callNumber, cc);
		}
		if (returnNumber == null){
			Intent i = new Intent();
			i.setClassName("com.urnum","com.csipsimple.ui.WebLogOn");
//			i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
			startActivityForResult(i, WEB_LOGON_REQUEST);
		}
		return returnNumber;
	}
	
	protected void onActivityResult(int requestCode, int resultCode,
            Intent data) {
        if (requestCode == WEB_LOGON_REQUEST) {
            if (resultCode == WebLogOn.RESULT_CONNECTION_OK) {
    			try {
    				bNumber = executeHttpGet(callNumber);
    				bNumber = numberFromUrnum(bNumber);
    				if (bNumber!=null) {
    				makeCall(callNumber, cc, bNumber);
    				}
    			} catch (Exception e) {			
    				alert.show();
    				e.printStackTrace();
    			}

			 }
            else if (resultCode == WebLogOn.RESULT_CANCEL ) {
            	db.close();
            	finish();
            }
            else if (resultCode == RESULT_CANCELED ) {
    			Intent i = new Intent();
    			i.setClassName("com.urnum","com.csipsimple.ui.WebLogOn");
 //   			i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
    			startActivityForResult(i, WEB_LOGON_REQUEST);
            }
          }
        }

	
	/** Called when the activity is first created. */
	@Override   
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setTitle("URNum");
		db = new DBAdapter(this);
		db.open();
		
	    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
	    cc = telephonyManager.getNetworkCountryIso(); 
	    aNumber = telephonyManager.getLine1Number();
		
		callNumber = PhoneNumberUtils.getNumberFromIntent(getIntent(), this);
		if(callNumber == null) {
			callNumber = getIntent().getData().getSchemeSpecificPart();
				}	

		alert = new AlertDialog.Builder(OutgoingPSTN.this);
		 
		alert.setTitle("Network not available");
		alert.setMessage("Turn on Mobile Data Network.        (Will use less than 0.1Kb pr call)");

		alert.setPositiveButton("Connected", new DialogInterface.OnClickListener()
		{  public void onClick(DialogInterface dialog, int id) {
			try {
				bNumber = executeHttpGet(callNumber);
				bNumber = numberFromUrnum(bNumber);
				if (bNumber!=null) {
				makeCall(callNumber, cc, bNumber);
				}
			} catch (Exception e) {			
				alert.show();
				e.printStackTrace();
			}
			
			
			} });
		
		
		alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
		{  public void onClick(DialogInterface dialog, int id) {
			db.close();
			finish();}
		});
	
		
		
		try {
			bNumber = executeHttpGet(callNumber);
			bNumber = numberFromUrnum(bNumber);
			if (bNumber!=null) {
			makeCall(callNumber, cc, bNumber);
			}
		} catch (Exception e) {
			bNumber = db.getShortcode(callNumber, cc);
			if (bNumber != null)
			{makeCall(callNumber, cc, bNumber);}
			else		
			{alert.show();};
			e.printStackTrace();
		}
		
	
	};
	
		
//		};
		
		private void makeCall(String callNumber, String cc, String bNumber)
		{
		int l;
		TextView tv = new TextView(this);
		tv.setText("Calling: "+callNumber+"->"+bNumber);
		setContentView(tv);
		
		db.insertShortcode(callNumber, cc, bNumber);
	
		
		ArrayList<ContentProviderOperation> ops =
		          new ArrayList<ContentProviderOperation>();

		
		ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
    	        .withSelection(ContactsContract.Data.MIMETYPE + " = ? AND " + 
    	        		ContactsContract.CommonDataKinds.Phone.DATA1 + " = ? ",
    	        new String[] {ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, String.valueOf(bNumber) })
    	        .withValue(ContactsContract.CommonDataKinds.Phone.DATA, "")
    	        .build());
		try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);}
		catch (Exception e) {
			e.printStackTrace();
		}
		
	    ContentResolver localContentResolver = getContentResolver();
		Cursor contactLookupCursor =
				localContentResolver.query(
				Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
				Uri.encode(callNumber)), 
				new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE},
				null,
				null,
				null); 
		try { contactLookupCursor.moveToFirst(); 
			callName = contactLookupCursor.getString(contactLookupCursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME));
			cachedCallName=callName;
			cachedCallType=contactLookupCursor.getString(contactLookupCursor.getColumnIndex(PhoneLookup.TYPE));

			l = callName.length();
			if (l>11) l=11;
			callName = callName.substring(0, l);
		}
		catch (Exception e) {
			callName="URNum";
			cachedCallName=null;
			e.printStackTrace();
		}
				finally { contactLookupCursor.close(); }
		
		callName = callName+":"+callNumber+"->"; 		
		createContactEntry(callName, bNumber);
	    
		 mListener = new CallStartListenerOut();  
	     mTelMgr = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);    
	     mTelMgr.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE);  
	  
	     Intent callIntent = new Intent(Intent.ACTION_CALL); 
        callIntent.setData(Uri.parse("tel:"+bNumber)); 
        callStart = System.currentTimeMillis();
        startActivity(callIntent); 
       
        db.close();
        finish();
		}
	
	    protected ContentProviderResult[] createContactEntry(String name, String phone) {
	        // Get values from UI
	        int phoneType =  ContactsContract.CommonDataKinds.Phone.TYPE_WORK;
	       
	        
	        // Prepare contact creation request
	        //
	        // Note: We use RawContacts because this data must be associated with a particular account.
	        //       The system will aggregate this with any other data for this contact and create a
	        //       coresponding entry in the ContactsContract.Contacts provider for us.
	        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
	        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
	                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, "com.example.android.contactmanager.ContactsAdder.ACCOUNT_TYPE")
	                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, "com.example.android.contactmanager.ContactsAdder.ACCOUNT_NAME")
	                .build());
	       ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
	                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
	                .withValue(ContactsContract.Data.MIMETYPE,
	                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
	                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
	                .build());
	        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
	                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
	                .withValue(ContactsContract.Data.MIMETYPE,
	                        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
	                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
	                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType)
	                .build());

	        // Ask the Contact provider to create a new contact
	       try {
	            return getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
	        } catch (Exception e) {
	            // Display warning
	            Context ctx = getApplicationContext();
	            CharSequence txt = "Error contact creation";
	            int duration = Toast.LENGTH_SHORT;
	            Toast toast = Toast.makeText(ctx, txt, duration);
	            toast.show();

	            // Log exception
	            e.printStackTrace();     
	            return null;}
	    }
	    
	    
	    public class CallStartListenerOut extends PhoneStateListener {
	    	boolean called = false;
	    	@Override
	    	public void onCallStateChanged(int state, String incomingNumber){
	    		super.onCallStateChanged(state, incomingNumber); 
	    		// Don't fire before the call was made  
	    		if (state == TelephonyManager.CALL_STATE_OFFHOOK)
	    			called = true;
	    			
	    		if (called && state == TelephonyManager.CALL_STATE_IDLE) {
	    			called = false;    
	    			 ArrayList<ContentProviderOperation> ops =
	    		        		new ArrayList<ContentProviderOperation>();
	    		        ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI)
	    		        		.withSelection(Data.DISPLAY_NAME + "=?", new String[]{String.valueOf(callName)})
	    		        		.build());
	    		        try {getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
	    				} catch (Exception e) {
	    					e.printStackTrace();
	    				}
	    				
	    		        ContentResolver contentResolver = getApplicationContext().getContentResolver();
	
	    		        Cursor c=contentResolver.query(CallLog.Calls.CONTENT_URI,
	    						null,
	    						CallLog.Calls.NUMBER+"=? AND "+CallLog.Calls.TYPE+"=?",
	    						new String[] {bNumber, String.valueOf(CallLog.Calls.OUTGOING_TYPE)},
	    						CallLog.Calls.DATE+" DESC");
	    			    
	    		        
	    		        ContentValues read_cv = null;
	    		        if (c!=null) {
	    		        if (c.moveToFirst()){
	    		        	read_cv = new ContentValues();
	    		        	DatabaseUtils.cursorRowToContentValues(c, read_cv);
	    		        	if  (read_cv.getAsLong(CallLog.Calls.DATE)>(callStart-1000)) {
	    		        		contentResolver.delete(CallLog.Calls.CONTENT_URI, 
								CallLog.Calls._ID+"=?", 
								new String[] {read_cv.getAsString(CallLog.Calls._ID)});				
	    		        		}
	    		        	else { read_cv = null;}
	    		        }
	    		        }
	    		        
	    		        ContentValues cv = new ContentValues();	    		        
	    		        cv.put(CallLog.Calls.NUMBER, callNumber);    		       
	    		        cv.put(CallLog.Calls.TYPE, CallLog.Calls.OUTGOING_TYPE);
	    		        cv.put(CallLog.Calls.NEW, 0);
	    		        
	    		        if (read_cv==null) {
	    		        cv.put(CallLog.Calls.DURATION,  (System.currentTimeMillis()-callStart)/1000);
	       		        cv.put(CallLog.Calls.DATE, System.currentTimeMillis());
	    		        }
	    		        else {
		    		        cv.put(CallLog.Calls.DURATION, read_cv.getAsString(CallLog.Calls.DURATION));
		       		        cv.put(CallLog.Calls.DATE, read_cv.getAsString(CallLog.Calls.DATE));
	    		        }  		        	

	    				if (cachedCallName!=null){
	    					cv.put(CallLog.Calls.CACHED_NAME, cachedCallName);
	    					cv.put(CallLog.Calls.CACHED_NUMBER_TYPE, cachedCallType);
	    					}
	    				contentResolver.insert(CallLog.Calls.CONTENT_URI, cv);
	    		        
	    		        
	    		        
	        
	    			mTelMgr.listen(this, PhoneStateListener.LISTEN_NONE); 
	    			
	    			
	    			
	    	
	    		} 
	    	} 
	    
	    
	    }    
}

		


